﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;

namespace engine
{
    /// <summary>
    /// Scene class
    /// Represents scene graph
    /// </summary>
    public class Scene
    {
        public ContentManager Content { get { return content; } }
        public Terrain Terrain { get { return terrain; } }
        public SceneNode Root { get { return root; } }
        public Camera Camera { get { return camera; } }

        private ContentManager content = null;
        private Terrain terrain = null;
        private SceneNode root = null;
        private Camera camera = null;





        /// <summary>
        /// Constructor
        /// Creates empty children list
        /// </summary>
        public Scene() : this(new List<SceneNode>()) { }

        /// <summary>
        /// Constructor
        /// Creates root with received children list
        /// </summary>
        /// <param name="rootChildren">Children list of root (main scene objects)</param>
        public Scene(List<SceneNode> rootChildren)
        {
            root = new SceneNode();
            root.Local = Matrix.Identity;
            root.Children.AddRange(rootChildren);
        }

        public void Initialize(Camera theCamera, float aspectRatio)
        {
            camera = theCamera;

            terrain = new Terrain();
            terrain.Initialize(this);
        }

        public void LoadContent(ContentManager theContent)
        {
            content = theContent;
            terrain.LoadContent();
        }

        /// <summary>
        /// Method called by Update method in Engine class
        /// </summary>
        /// <param name="gameTime"></param>
        public void Update(GameTime gameTime)
        {
            camera.Update();
            root.Update(gameTime);
        }

        /// <summary>
        /// Called by Draw method in Engine class
        /// </summary>
        /// <param name="gameTime"></param>
        public void Draw(GameTime gameTime)
        {
            terrain.Draw(gameTime);
            root.Draw(gameTime, Matrix.Identity);
        }

        /// <summary>
        /// Assumes that parent already exists in the scene.
        /// Expects the node that has been constructed, but not initialized
        /// </summary>
        /// <param name="nodeToAdd"></param>
        /// <param name="parentNode"></param>
        public void AddNode(SceneNode node, SceneNode parentNode)
        {
            parentNode.Children.Add(node);
            node.ParentNode = parentNode;
            node.Initialize(this);
            node.LoadContent();            
        }

        public void AddNode(SceneNode node)
        {
            AddNode(node, root);
        }

        public void RemoveNode(SceneNode node)
        {
            node.ParentNode.Children.Remove(node);
            node.ParentNode = null;
        }

    }
}
